﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using System.Globalization;

namespace The_LarX
{
    public static class Vector3Util
    {
        /// <summary>
        /// Returns X + Y + Z / 3
        /// </summary>
        /// <param name="vec"></param>
        /// <returns></returns>
        public static float Average(Vector3 vec)
        {
            return (vec.X + vec.Y + vec.Z) / 3;
        }

        /// <summary>
        /// Converts a Rotation Vector3 from Degrees to Radians
        /// </summary>
        /// <param name="vec"></param>
        /// <returns></returns>
        public static Vector3 ToRadians(Vector3 vec)
        {
            return new Vector3(MathHelper.ToRadians(vec.X),
                MathHelper.ToRadians(vec.Y),
                MathHelper.ToRadians(vec.Z));
        }

        /// <summary>
        /// Converts a Rotation Vector3 from Radians to Degrees
        /// </summary>
        /// <param name="vec"></param>
        /// <returns></returns>
        public static Vector3 ToDegrees(Vector3 vec)
        {
            return new Vector3(MathHelper.ToDegrees(vec.X),
                MathHelper.ToDegrees(vec.Y),
                MathHelper.ToDegrees(vec.Z));
        }

        public static List<Vector3> PointsAroundCircle(float Radius, float Y)
        {
            List<Vector3> list = new List<Vector3>();
            
            float radius = Radius;
            double angleStep = 15f / radius;
            Vector3 Offset = new Vector3(radius, 0, radius);

            // Middle lights
            for (double angle = 0; angle < Math.PI * 2; angle += angleStep)
            {
                int x = (int)Math.Round(radius + radius * Math.Cos(angle));
                int y = (int)Math.Round(radius + radius * Math.Sin(angle));

                Vector3 pos = new Vector3(x, Y, y);
                pos -= Offset;
                list.Add(pos);
            }

            return list;
        }

        /// <summary>
        /// Returns a Vector3 with Half values(0.5f)
        /// </summary>
        /// <returns></returns>
        public static Vector3 Half
        {
            get { return new Vector3(0.5f); }
        }

        /// <summary>
        /// Formats the Vector3 to a String. "Equivalent" to the ToString(), but gives a nicer
        /// way to show the Vector3 as a string.
        /// </summary>
        /// <param name="vec">The Vector to format</param>
        /// <returns></returns>
        public static string Format(Vector3 vec)
        {
            return "X:" + vec.X + "Y:" + vec.Y + "Z:" + vec.Z;
        }
        /// <summary>
        /// Formats the Vector3 to a String. "Equivalent" to the ToString(), but gives a nicer
        /// way to show the Vector3 as a string.
        /// </summary>
        /// <param name="vec">The Vector to format</param>
        /// <param name="X">The X representation value</param>
        /// <param name="Y">The Y representation value</param>
        /// <param name="Z">The Z representation value</param>
        /// <returns></returns>
        public static string Format(Vector3 vec, string X, string Y, string Z)
        {
            return X + vec.X + Y + vec.Y + Z + vec.Z;
        }
        /// <summary>
        /// Formats the Vector3 to a String. "Equivalent" to the ToString(), but gives a nicer
        /// way to show the Vector3 as a string.
        /// </summary>
        /// <param name="vec">The Vector to format</param>
        /// <param name="X">The X representation value</param>
        /// <param name="Y">The Y representation value</param>
        /// <param name="Z">The Z representation value</param>
        /// <param name="charOffset">Populate and add Empty Spaces, so the string won't move</param>
        /// <returns></returns>
        public static string Format(Vector3 vec, string X, string Y, string Z, int charOffset)
        {
            string vecX = vec.X.ToString();
            while (vecX.Length < charOffset)
            {
                vecX = " " + vecX;
            }
            string vecY = vec.Y.ToString();
            while (vecY.Length < charOffset)
            {
                vecY = " " + vecY;
            }
            string vecZ = vec.Z.ToString();
            while (vecZ.Length < charOffset)
            {
                vecZ = " " + vecZ;
            }
            return X + vecX + Y + vecY + Z + vecZ;
        }

        /// <summary>
        /// Returns the X, Y and Z values of a Vector4 in a Vector3.
        /// </summary>
        /// <param name="vec">The Vector4 you wnat to convert</param>
        /// <returns>A vector3 with the Vector4 values</returns>
        public static Vector3 Vector4ToVector3(Vector4 vec)
        {
            return new Vector3(vec.X, vec.Y, vec.Z);
        }

        public static float ArcTanAngle(float X, float Y)
        {
            if (X == 0)
            {
                if (Y == 1)
                    return (float)MathHelper.PiOver2;
                else
                    return (float)-MathHelper.PiOver2;
            }
            else if (X > 0)
                return (float)Math.Atan(Y / X);
            else if (X < 0)
            {
                if (Y > 0)
                    return (float)Math.Atan(Y / X) + MathHelper.Pi;
                else
                    return (float)Math.Atan(Y / X) - MathHelper.Pi;
            }
            else
                return 0;
        }

        /// <summary>
        /// Creates a Vector3 from a String
        /// Usage: X:Y:Z
        /// Use dots for decimal
        /// </summary>
        /// <param name="sk"></param>
        /// <returns></returns>
        public static Vector3 CreateFromString(string sk)
        {
            string[] values = sk.Split(':');
            Vector3 Vector = new Vector3(
                float.Parse(values[0], CultureInfo.InvariantCulture),
                float.Parse(values[1], CultureInfo.InvariantCulture),
                float.Parse(values[2], CultureInfo.InvariantCulture));
            return Vector;
        }

        /// <summary>
        /// Returns Euler angles that point from one point to another
        /// </summary>
        /// <param name="from"></param>
        /// <param name="location"></param>
        /// <returns></returns>
        public static Vector3 AngleTo(Vector3 from, Vector3 location)
        {
            Vector3 angle = new Vector3();
            Vector3 v3 = Vector3.Normalize(location - from);
            angle.X = (float)Math.Asin(v3.Y);
            angle.Y = ArcTanAngle(-v3.Z, -v3.X);
            return angle;
        }
    }
}
